#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>

#include "../include/filesystem.h"
#include "../include/general.h"

static int conflictFilter(const struct dirent *dit);

int
canCommit(const char *path)
{
    struct dirent **namelist;
    int i, read = 0;
    int ret = 1;

    read = scandir(path, &namelist, conflictFilter, NULL);

    if (read > 0)
    {
        ret = 0;
        printf("Can't sync. There are %d conflict(s)\n", read);

        for(i = 0; i < read; i++)
        {
            printf("%s\n", namelist[i]->d_name);
            free(namelist[i]);
        }

        free(namelist);
    }

    return ret;
}

static int
conflictFilter(const struct dirent *dit)
{
    char *ext = fileExt(dit->d_name);

    if (ext)
        if ((strcmp(ext, ".mine")) == 0)
            return 1;

    return 0;
}

int
startFolder(char *path)
{
    DIR *dip;
    struct dirent *dit;
    int i = 0, ret = 0;
    char currPath[FILE_LEN];

    switch (isDir(path))
    {
        /*It's a dir!*/
        case 1:
            break;

        /*It's a file!*/
        case 0:
            printf ("Couldn't create folder.\n%s exists and it's a file\n", path);
            return 0;

        /*It's me! MARIO!*/
        default:
            return ((mkdir(path, 0744)) == -1) ? 0:1;

    }

    /*
    * Open a directory stream to argv[1] and make sure
        * it's a readable and valid (directory) */
    if ((dip = opendir(path)) == NULL)
    {
        perror("opendir");
        return 0;
    }

    /*
    * Read in the files from argv[1] and print */
    while ((dit = readdir(dip)) != NULL)
    {
        i++;
        sprintf(currPath, "%s/%s", path, dit->d_name);

        /*TODO: Si se le pasa un path roto es probable que muera,
        no se pone ahora porque toda la info sale de readdir */
        if (isDir(currPath))
        {
            if ( 0 == strcmp(".", dit->d_name) ||
                 0 == strcmp("..", dit->d_name) )
                continue;

            startFolder(currPath);
        }
        else
        {
            if ( strcmp(fileExt(dit->d_name), ".old") )
            {
                char dest[FILE_LEN];

                sprintf(dest, "%s%s", currPath, ".old");
                ret = mv(currPath, dest);
            }
        }
    }

    /* Close the stream to argv[1]. And check for errors. */
    if (closedir(dip) == -1)
    {
        perror("closedir");
        return 0;
    }

    return 1;
}

int
cp(const char *old, const char *new)
{
    FILE *in, *out;
    char ch;

    if (old == NULL || new == NULL)
        return -1;

    if (isDir(old))
        return -1;


    if((in=fopen(old, "rb")) == NULL)
        return -1;

    if((out=fopen(new, "wb")) == NULL)
        return -1;

    while(!feof(in))
    {
        ch = getc(in);

        if(ferror(in))
            return -1;
        else
        {
            if(!feof(in)) putc(ch, out);
                if(ferror(out))
                    return -1;
        }
    }

    fclose(in);
    fclose(out);
    return 1;
}

int
mv(const char *old, const char *new)
{
    if (old == NULL || new == NULL)
        return -1;

    if (isDir(old))
        return -2;

    if (link(old, new) == -1)
        return -3;

    if (unlink(old) == -1)
    {
        unlink(new);
        return -4;
    }

    return 0;
}

int
rm(const char *path)
{
    if (NULL == path)
        return -1;

    if (unlink(path) == -1)
    {
        return -1;
    }

    return 0;
}

int
isDir(const char *path)
{
    int retval;
    struct stat statbuf;

  // Make sure the path exists, and is a directory
    retval = lstat(path, &statbuf);

  // If something bad happened while doing the stat
    if(retval == -1)
    {
//         if(errno == ENOENT)
//             printf("Error: Specified path \"%s\" doesn't exist\n", path);
//         else if (errno == EACCES)
//             printf("Error: Invalid permissions for specified path \"%s\"\n", path);
//         else
//             printf("Error calling stat on \"%s\"\n", path);
//
//         exit(-1);
        return -2;
    }

  // Is it actually a directory? => if it's return 1
    return(S_ISDIR(statbuf.st_mode));
}

int
modTime(const char *path)
{
    int retval;
    struct stat statbuf;

  // Make sure the path exists, and is a directory
    retval = lstat(path, &statbuf);

  // If something bad happened while doing the stat
    if(retval == -1)
    {
        return -2;
    }

    return (int)statbuf.st_mtime;
}

char *
fileExt(const char *src)
{
    char *var;
    var = strrchr(src, '.');

    return (var == NULL) ? "" : var;
}

